/***************************************************************************
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************
 * File Name: optSwitch.cpp                                                *
 * Author:    Graeme                                                       *
 * Class:     OptSwitch                                                    *
 * Copyright (C) 2008  Graeme Foster                                       *
 **************************************************************************/
#include "optSwitch.h"
/*****************************************************************************
 * Private Methods
 *****************************************************************************/

/*! \internal This will instantiate an instance of the OptSwitch class.
  * This initialises all the details of the switch. Because it is private
  * instances can only be created by friend a class, which is OptManager.
  */
OptSwitch::OptSwitch(QChar abbrev, QString fullName, QString args, ActionFuncPtr actionMethod, CloseFuncPtr exitMethod, switchStyle style)
{
   _shortName = abbrev.isLetterOrNumber()?abbrev:QChar::Null;
   _longName = fullName;
   _description = QString();
   _actualArgList.clear();
   QStringList argParts = args.split(" ", QString::SkipEmptyParts);
   for (int i = 0; i < argParts.size(); ++i)
   {
      OptArgument * oa = new OptArgument(argParts[i]);
      if (oa->isMandatory())
         _mandatoryArgList.append(oa);
      else
         _optionalArgList.append(oa);
   }
   _actionFn = actionMethod;
   _closeFn = exitMethod;
   _style = style;
}

/*! \internal returns a string with the details of the switch
 * it will display the short name,if one exists otherwise the long name
 * followed by the details of the arguments that are supported
 */
QString OptSwitch::brief()
{
   QString msg;
   if (_shortName.isNull())
      msg = "--" + _longName;
   else
      msg = QString(" -") + _shortName;
   msg += fullArgList();
   return msg;
}

/*! \internal returns a string with the details of the switch
 * it will display the short name, if one exists, then the long name
 * followed by the details of the arguments that are supported
 */
QString OptSwitch::help()
{
   QString msg;
   if (_shortName.isNull())
      msg = "    ";
   else
      msg = QString("  -") + _shortName;
   msg += " --" + _longName;
   msg += fullArgList();
   if (!_description.isEmpty())
   {
      msg += "\n" + format80(_description) + "\n";
   }
   return msg;
}

/*! \internal returns a string with the details of the switch
 * it will display the long name followed by the arguments that are supported
 */
QString OptSwitch::dump()
{
   QString details = _longName + ":";
   for (int i = 0; i < _actualArgList.size(); ++i)
   {
      details += " " + _actualArgList[i];
   }
   return details;
}

/*! \internal returns a string with the details of the mandatory
 * and optional arguments that this switch supports
 */
QString OptSwitch::fullArgList()
{
   QString msg;
   for (int i =0; i < _mandatoryArgList.size(); ++i)
   {
      msg += " " + _mandatoryArgList[i]->help();
   }
   for (int i =0; i < _optionalArgList.size(); ++i)
   {
      msg += " " + _optionalArgList[i]->help();
   }
   return msg;
}

/*! \internal This method is used to format the output so that it fits within a screen
    80 characters wide and a margin of five characters; both figures are hard-wired.
 */
QString OptSwitch::format80(const QString & msg)
{
   QStringList list = msg.split(QRegExp("\\s+"));
   QString margin = "     ";
   QString formatted = margin;
   int size = formatted.size();
   for (int i = 0; i<list.size(); ++i)
   {
      if (size + list[i].size() >= 80)
      {
         formatted += "\n"+margin+list[i]+" ";
         size = 4 + list[i].size();
      }
      else
      {
         formatted += list[i] + " ";
         size += 1 + list[i].size();
      }
   }
   return formatted;
}
